function InitSlot(slotPanel, itemIndex, containerIndex, slotIndex)
{
	if (itemIndex == undefined || itemIndex == null) itemIndex = -1;

	var initEvent = (slotPanel.itemIndex == undefined);

	slotPanel.itemIndex = itemIndex;
	slotPanel.containerIndex = containerIndex;
	slotPanel.slotIndex = slotIndex;


	if (initEvent)
	{
		slotPanel.BLoadLayoutSnippet("Slot");

		//event
		slotPanel.SetPanelEvent("onmouseover", 
			function()
			{
				if (slotPanel.itemIndex == -1) return;
				// var localHeroIndex = Players.GetPlayerHeroEntityIndex(Players.GetLocalPlayer());

				// $.DispatchEvent("DOTAShowAbilityInventoryItemTooltip", slotPanel, localHeroIndex, slotPanel.slot_index);
			}
		);
		slotPanel.SetPanelEvent("onmouseout", 
			function()
			{
				// $.DispatchEvent( "DOTAHideAbilityTooltip", slotPanel);
			}
		);
		slotPanel.SetPanelEvent("onactivate", 
			function()
			{
				if (slotPanel.itemIndex == -1) return;
				// var localHeroIndex = Players.GetPlayerHeroEntityIndex(Players.GetLocalPlayer());

				// Abilities.ExecuteAbility(slotPanel.itemIndex, Players.GetLocalPlayerPortraitUnit(), false);
			}
		);
		slotPanel.SetPanelEvent("ondblclick", 
			function()
			{
				if (slotPanel.itemIndex == -1) return;
				if (!GameUI.IsMouseDown(0)) return;
				// var localHeroIndex = Players.GetPlayerHeroEntityIndex(Players.GetLocalPlayer());

				// Abilities.CreateDoubleTapCastOrder(slotPanel.itemIndex, localHeroIndex);

				var params = {
					containerIndex : Number(slotPanel.containerIndex),
					slotIndex : Number(slotPanel.slotIndex),
					isShiftDown : GameUI.IsShiftDown(),
					isCtrlDown : GameUI.IsControlDown(),
				};
				GameEvents.SendCustomGameEventToServer("equip_or_unequip_equipment", params);
			}
		);
		slotPanel.SetPanelEvent("oncontextmenu", 
			function()
			{
				if (slotPanel.itemIndex == -1)
				{
					return;
				}
				if (! Entities.IsControllableByPlayer(Players.GetLocalPlayerPortraitUnit(), Players.GetLocalPlayer()))
				{
					return;
				}

				var params = {
					containerIndex : Number(slotPanel.containerIndex),
					slotIndex : Number(slotPanel.slotIndex),
					isShiftDown : GameUI.IsShiftDown(),
					isCtrlDown : GameUI.IsControlDown(),
				};
				GameEvents.SendCustomGameEventToServer("quick_move_item", params);
			}
		);
		slotPanel.SetDraggable(true);
		$.RegisterEventHandler("DragStart", slotPanel, 
			function(panelId, dragCallbacks)
			{
				if (slotPanel.itemIndex == -1)
				{
					return true;
				}
				if (! Entities.IsControllableByPlayer(Players.GetLocalPlayerPortraitUnit(), Players.GetLocalPlayer()))
				{
					return true;
				}

				// $.DispatchEvent("DOTAHideAbilityTooltip", slotPanel);

				var displayPanel = $.CreatePanel("DOTAItemImage", slotPanel, "dragImage");
				displayPanel.contextEntityIndex = slotPanel.itemIndex;
				displayPanel.DragPanel = slotPanel;
				displayPanel.DragCompleted = false;
				displayPanel.style.width = "70.8px";
				displayPanel.style.height = "54px";
				displayPanel.DeleteAsync(7.5);
				

				dragCallbacks.displayPanel = displayPanel;
				dragCallbacks.offsetX = 0;
				dragCallbacks.offsetY = 0;
				
				slotPanel.AddClass("dragging_from");
				return true;
			}
		);
		$.RegisterEventHandler("DragEnter", slotPanel, 
			function(panelId, draggedPanel)
			{
				var DragPanel = draggedPanel.DragPanel;

				if (DragPanel == undefined || DragPanel == null || DragPanel == slotPanel)
					return true;

				slotPanel.AddClass("potential_drop_target");
				return true;
			}
		);
		$.RegisterEventHandler("DragLeave", slotPanel, 
			function(panelId, draggedPanel)
			{
				var DragPanel = draggedPanel.DragPanel;

				if (DragPanel == undefined || DragPanel == null || DragPanel == slotPanel)
					return false;

				slotPanel.RemoveClass("potential_drop_target");
				return true;
			}
		);
		$.RegisterEventHandler("DragDrop", slotPanel, 
			function(panelId, draggedPanel)
			{
				var DragPanel = draggedPanel.DragPanel;
				
				if (DragPanel == undefined || DragPanel == null)
					return true;

				draggedPanel.DragCompleted = true;

				if (DragPanel == slotPanel)
					return true;

				var params = {
					containerIndex1 : Number(DragPanel.containerIndex),
					slotIndex1 : Number(DragPanel.slotIndex),
					containerIndex2 : Number(slotPanel.containerIndex),
					slotIndex2 : Number(slotPanel.slotIndex),
					isShiftDown : GameUI.IsShiftDown(),
					isCtrlDown : GameUI.IsControlDown(),
				};
				GameEvents.SendCustomGameEventToServer("swap_items", params);

				return true;
			}
		);
		$.RegisterEventHandler("DragEnd", slotPanel, 
			function(panelId, draggedPanel)
			{
				if (! draggedPanel.DragCompleted)
				{
					var entityIndex = GetCursorEntity();
					if (entityIndex != -1 && !Entities.IsItemPhysical(entityIndex) && entityIndex != Players.GetLocalPlayerPortraitUnit())
					{
						Game.PrepareUnitOrders(
							{
								UnitIndex: Players.GetLocalPlayerPortraitUnit(),
								OrderType: dotaunitorder_t.DOTA_UNIT_ORDER_GIVE_ITEM,
								TargetIndex: entityIndex,
								AbilityIndex: -2,
							}
						);

						var params = {
							containerIndex : Number(slotPanel.containerIndex),
							itemIndex : slotPanel.itemIndex,
							targetIndex : entityIndex,
							isShiftDown : GameUI.IsShiftDown(),
							isCtrlDown : GameUI.IsControlDown(),
						};
						GameEvents.SendCustomGameEventToServer("give_item", params);
					}
					else
					{
						var cursor = GameUI.GetCursorPosition();

						Game.PrepareUnitOrders(
							{
								UnitIndex: Players.GetLocalPlayerPortraitUnit(),
								OrderType: dotaunitorder_t.DOTA_UNIT_ORDER_DROP_ITEM,
								Position: Game.ScreenXYToWorld(cursor[0], cursor[1]),
								AbilityIndex: -2,
							}
						);

						var params = {
							containerIndex : Number(slotPanel.containerIndex),
							itemIndex : slotPanel.itemIndex,
							position : Game.ScreenXYToWorld(cursor[0], cursor[1]),
							isShiftDown : GameUI.IsShiftDown(),
							isCtrlDown : GameUI.IsControlDown(),
						};
						GameEvents.SendCustomGameEventToServer("drop_item", params);
					}
				}

				draggedPanel.DeleteAsync(-1);

				slotPanel.RemoveClass("dragging_from");
				return true;
			}
		);
	}
	UpdateSlot(slotPanel);
}

function RemoveSlot(slotPanel)
{
	slotPanel.ClearPanelEvent("onmouseover");
	slotPanel.ClearPanelEvent("onmouseout");
	slotPanel.ClearPanelEvent("onactivate");
	slotPanel.ClearPanelEvent("ondblclick");
	slotPanel.ClearPanelEvent("oncontextmenu");
	slotPanel.DeleteAsync(-1);
}

function UpdateSlot(slotPanel)
{
	var item = slotPanel.itemIndex;
	var itemData = GetItemDataByIndex(slotPanel.itemIndex);
// {"isEquipment":1,"container":17,"finiteusesTotal":100,"finiteusesConsumption":{"CutTree":1,"Attack":1},"":100,"equipmentsSlot":1,"isFiniteUses":1}
	slotPanel.FindChildTraverse("ItemImage").contextEntityIndex = item;

	var isFiniteUses = false;
	if (itemData != undefined && itemData.isFiniteUses != undefined && itemData.isFiniteUses == 1)
	{
		isFiniteUses = true;
		var percent = Math.ceil(itemData.finiteusesCurrent);
		slotPanel.SetDialogVariableInt("finite_uses_percent", percent);
	}
	slotPanel.SetHasClass("is_finite_uses", isFiniteUses);

	var chargeCount = 0;
	var hasCharges = false;
	var altChargeCount = 0;
	var hasAltCharges = false;
	if (Items.ShowSecondaryCharges(item))
	{
		// Ward stacks display charges differently depending on their toggle state
		hasCharges = true;
		hasAltCharges = true;
		if (Abilities.GetToggleState(item))
		{
			chargeCount = Items.GetCurrentCharges(item);
			altChargeCount = Items.GetSecondaryCharges(item);
		}
		else
		{
			altChargeCount = Items.GetCurrentCharges(item);
			chargeCount = Items.GetSecondaryCharges(item);
		}
	}
	else if (Items.ShouldDisplayCharges(item))
	{
		hasCharges = true;
		chargeCount = Items.GetCurrentCharges(item);
	}
	slotPanel.SetHasClass("show_charges", hasCharges);
	slotPanel.SetHasClass("show_alt_charges", hasAltCharges);
	slotPanel.SetDialogVariableInt("charge_count", chargeCount);
	slotPanel.SetDialogVariableInt("alt_charge_count", altChargeCount);

	var isPerishable = false;
	if (itemData != undefined && itemData.isPerishable != undefined && itemData.isPerishable == 1)
	{
		//perishTime,perishRemainingTime
		isPerishable = true;
		var percent = itemData.perishRemainingTime/itemData.perishTime;
		slotPanel.FindChildTraverse("PerishingBorder").style.clip = "radial(50.0% 50.0%, 0deg, "+(-360*percent)+"deg)";
		slotPanel.FindChildTraverse("PerishingBorder").style.backgroundColor = "rgb("+255*(1-percent)+","+255*percent+",0)";
	}
	else
	{
		slotPanel.FindChildTraverse("PerishingBorder").style.clip = "radial(50.0% 50.0%, 0deg, 0deg)";
	}
	slotPanel.SetHasClass("is_perishable", isPerishable);


	slotPanel.SetHasClass("is_active", Abilities.GetLocalPlayerActiveAbility() == item);
	slotPanel.SetHasClass("is_passive", Abilities.IsPassive(item));
	slotPanel.SetHasClass("item_phase", Abilities.IsInAbilityPhase(item));

	var muted = Abilities.IsMuted(item);
	slotPanel.SetHasClass("muted", muted);

	var cooldownLength = Math.max(Abilities.GetCooldownLength(item), Abilities.GetCooldown(item));
	if (cooldownLength == 0) cooldownLength = 1;
	var cooldownRemaining = Abilities.GetCooldownTimeRemaining(item);
	var cooldownPercent = cooldownRemaining/cooldownLength;
	slotPanel.FindChildTraverse("CooldownOverlay").style.clip = "radial(50.0% 50.0%, 0deg, "+(-360*cooldownPercent)+"deg)";
	slotPanel.FindChildTraverse("CooldownTimer").text = Math.ceil(cooldownRemaining);
	var cooldown_ready = Abilities.IsCooldownReady(item);
	slotPanel.SetHasClass("in_cooldown", item != -1 && ! cooldown_ready);
	slotPanel.SetHasClass("cooldown_ready", cooldown_ready);

	var can_cast_again = ! cooldown_ready || muted;
	if (!slotPanel.BHasClass("no_level") && slotPanel.BHasClass("can_cast_again") && slotPanel.BHasClass("can_cast_again") != can_cast_again)
	{
		slotPanel.FindChildTraverse("Shine").SetHasClass("do_shine", false);
		slotPanel.FindChildTraverse("Shine").SetHasClass("do_shine", true);
	}
	slotPanel.SetHasClass("can_cast_again", can_cast_again);
	slotPanel.SetHasClass("no_level", item == -1);
}

function UpdateSlots()
{
	$.Schedule(0, UpdateSlots);
	var slots = $.GetContextPanel().FindChildrenWithClassTraverse("Slot");
	for (var i = 0; i < slots.length; i++)
	{
		var slotPanel = slots[i];
		UpdateSlot(slotPanel);
	}
}

(function()
{
	UpdateSlots();
})();